package org.example;

import org.apache.ibatis.session.SqlSession;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.realm.text.IniRealm;
import org.apache.shiro.subject.Subject;
import org.example.domain.Employee;
import org.example.mapper.EmployeeMapper;
import org.example.realm.EmailRealm;
import org.example.realm.UserRealm;
import org.example.util.MyBatisUtil;
import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;

/**
 * @author 李新雨的项目86176
 * @version 1.0
 * @date 2024-12-14 16:50
 */
public class ShiroDemo {


    //此时数据在文件中    此时的Realm是Ini文件
    @Test
    public void testLoginByIni(){
      //安全管理器，数据源  subject主体
      //创建安全管理器  import org.apache.shiro.mgt.SecurityManager; 接口
        SecurityManager securityManager=new DefaultSecurityManager();
        //强制转换
        DefaultSecurityManager defaultSecurityManager= (DefaultSecurityManager) securityManager;
        //配置数据源，读取资源目录文件，封装到Realm中   map机会
        //// TODO: 2024/12/14   Realm中即--------------是数据库中的数据
        Realm realm=new IniRealm("classpath:shiro-authc.ini");
        IniRealm iniRealm= (IniRealm) realm;
//        System.out.println("-----------------------"+iniRealm.getIni().getSection("admin"));
        //将数据源添加到安全管理器中  ，可以设置多个Realm
        defaultSecurityManager.setRealm(iniRealm);
        //将安全管理器交给Shiro框架管理       静态-----private static SecurityManager securityManager;
        SecurityUtils.setSecurityManager(defaultSecurityManager);
        //在Shiro框架管理获取Subject对象 -------------- 即当前的登陆者
        //// TODO: 2024/12/14  使得subject与 SecurityManager ----------------在同一个环境中[SecurityUtils]
        //工厂类创建实现类对象
        /*
         * subject.setSecurityManager(SecurityUtils.getSecurityManager());
         *   使subject与 SecurityManager ----------------在同一个环境中[SecurityUtils]
         *   关联
         */
        Subject subject=SecurityUtils.getSubject();
        //验证当前用户是否登录
        if(!subject.isAuthenticated()){
            System.out.println("用户未登录，用户登录状态"+subject.isAuthenticated());
        }else {
            System.out.println("用户已登录，用户登录状态"+subject.isAuthenticated());
        }
        //// TODO: 2024/12/14   ------------------------------------- 封装账号和密码  令牌
        /***
         *
         * // TODO: 2024/12/14  抛异常    用户名   密码
         * 如果
         * 用户名错误
         * org.apache.shiro.authc.UnknownAccountException:
         * Realm [org.apache.shiro.realm.text.IniRealm@6833ce2c] was unable to find account data for the submitted AuthenticationToken
         * [org.apache.shiro.authc.UsernamePasswordToken - admin2, rememberMe=false].
         *
         * 密码错误
         * org.apache.shiro.authc.IncorrectCredentialsException: Submitted credentials for token
         * [org.apache.shiro.authc.UsernamePasswordToken - admin, rememberMe=false] did not match the expected credentials.
         */
        UsernamePasswordToken token=new UsernamePasswordToken("admin","123456");
        //subject对象调用login方法，进行登陆   实际上是  SecurityManager 调用login  方法
        //// TODO: 2024/12/14  委派给 SecurityManager 调用login  方法   ----------  委派给Realm--------->  数据源
        subject.login(token);
        //验证当前用户是否登录
        if(!subject.isAuthenticated()){
            System.out.println("用户未登录，用户登录状态"+subject.isAuthenticated());
        }else {
            System.out.println("用户已登录，用户登录状态"+subject.isAuthenticated());
        }
        //登出
        subject.logout();
        //验证当前用户是否登录
        if(!subject.isAuthenticated()){
            System.out.println("用户未登录，用户登录状态"+subject.isAuthenticated());
        }else {
            System.out.println("用户已登录，用户登录状态"+subject.isAuthenticated());
        }
    }


    //此时数据在数据库中   自定义Realm
    @Test
    public void testLoginByDB(){
        SecurityManager securityManager=new DefaultSecurityManager();
        //强制转换
        DefaultSecurityManager defaultSecurityManager= (DefaultSecurityManager) securityManager;
        UserRealm userRealm= new UserRealm();
        defaultSecurityManager.setRealm(userRealm);
        SecurityUtils.setSecurityManager(defaultSecurityManager);
        Subject subject=SecurityUtils.getSubject();
        if(!subject.isAuthenticated()){
            System.out.println("用户未登录，用户登录状态"+subject.isAuthenticated());
        }else {
            System.out.println("用户已登录，用户登录状态"+subject.isAuthenticated());
        }
        //// TODO: 2024/12/14   ------------------------------------- 封装账号和密码  令牌
        UsernamePasswordToken token=new UsernamePasswordToken("yl","888");
        //subject对象调用login方法，进行登陆   实际上是  SecurityManager 调用login  方法
        //// TODO: 2024/12/14  委派给 SecurityManager 调用login  方法   ----------  委派给Realm--------->  数据源
        subject.login(token);
        //验证当前用户是否登录
        if(!subject.isAuthenticated()){
            System.out.println("用户未登录，用户登录状态"+subject.isAuthenticated());
        }else {
            System.out.println("用户已登录，用户登录状态"+subject.isAuthenticated());
            System.out.println(subject.getPrincipal().toString());
        }
        //登出
        subject.logout();
        //验证当前用户是否登录
        if(!subject.isAuthenticated()){
            System.out.println("用户未登录，用户登录状态"+subject.isAuthenticated());
        }else {
            System.out.println("用户已登录，用户登录状态"+subject.isAuthenticated());
        }




    }

    @Test
    public void test1(){
        SqlSession session = MyBatisUtil.getSession();
        EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
        System.out.println(mapper.selectAll());


    }


    @Test
    public void test2(){
        SecurityManager securityManager=new DefaultSecurityManager();
        //强制转换
        DefaultSecurityManager defaultSecurityManager= (DefaultSecurityManager) securityManager;
        UserRealm userRealm= new UserRealm();
        EmailRealm emailRealm=new EmailRealm();
//        defaultSecurityManager.setRealm(userRealm);

        ArrayList<Realm> realms = new ArrayList<>();
        realms.add(userRealm);
        realms.add(emailRealm);
        //
        defaultSecurityManager.setRealms(realms);

        SecurityUtils.setSecurityManager(defaultSecurityManager);
        Subject subject=SecurityUtils.getSubject();
        if(!subject.isAuthenticated()){
            System.out.println("用户未登录，用户登录状态"+subject.isAuthenticated());
        }else {
            System.out.println("用户已登录，用户登录状态"+subject.isAuthenticated());
        }
        //// TODO: 2024/12/14   ------------------------------------- 封装账号和密码  令牌
        UsernamePasswordToken token=new UsernamePasswordToken("11111111@@qq.com","7777777");
        //subject对象调用login方法，进行登陆   实际上是  SecurityManager 调用login  方法
        //// TODO: 2024/12/14  委派给 SecurityManager 调用login  方法   ----------  委派给Realm--------->  数据源
        subject.login(token);
        //验证当前用户是否登录
        if(!subject.isAuthenticated()){
            System.out.println("用户未登录，用户登录状态"+subject.isAuthenticated());
        }else {
            System.out.println("用户已登录，用户登录状态"+subject.isAuthenticated());
            Object principal = subject.getPrincipal();
            Employee employee = (Employee) principal;
            employee.setPassword("********");
            System.out.println("当前登录的用户信息：："+subject.getPrincipal().toString());
        }
        //登出
        subject.logout();
        //验证当前用户是否登录
        if(!subject.isAuthenticated()){
            System.out.println("用户未登录，用户登录状态"+subject.isAuthenticated());
        }else {
            System.out.println("用户已登录，用户登录状态"+subject.isAuthenticated());
        }




    }

    @Test
    public void testAuthorByIni(){
        SecurityManager securityManager=new DefaultSecurityManager();
        DefaultSecurityManager defaultSecurityManager= (DefaultSecurityManager) securityManager;
//        UserRealm userRealm= new UserRealm();
        IniRealm iniRealm=new IniRealm("classpath:shiro-authc.ini");
        defaultSecurityManager.setRealm(iniRealm);
        SecurityUtils.setSecurityManager(defaultSecurityManager);
        Subject subject=SecurityUtils.getSubject();
        UsernamePasswordToken token=new UsernamePasswordToken("cg","666");
        subject.login(token);
        if(!subject.isAuthenticated()){
            System.out.println("用户未登录，用户登录状态"+subject.isAuthenticated());
        }else {
            System.out.println("用户已登录，用户登录状态"+subject.isAuthenticated());
            System.out.println("当前登录的用户信息：："+subject.getPrincipal().toString());
        }

        //
        System.out.println("当前用户是否有权限:"+subject.isPermitted("customer:list"));
        System.out.println("当前用户是否有权限:"+subject.isPermitted("user:list"));
        //
        boolean[] permitted = subject.isPermitted("user:list", "customer:list");
        for (boolean b : permitted) {
            System.out.println(b);
        }

        boolean permittedAll = subject.isPermittedAll("customer:list", "user:list");
        System.out.println(permittedAll);

        //没有权限抛异常
        subject.checkPermission("customer:list");


        //
        System.out.println("---------------------------------------");
        System.out.println("当前用户是否有角色:"+subject.hasRole("hr"));
        System.out.println("当前用户是否有角色:"+subject.hasRole("seller"));
        boolean[] roles = subject.hasRoles(Arrays.asList("hr", "seller"));

        //没有角色抛异常
        subject.checkRole("hr");



    }



    @Test
    public void testAuthorByDb(){








    }

}

